package org.opengauss.evaluate.paeser.sqlparser.fileinput;

import com.alibaba.fastjson.JSON;
import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseResult;
import com.github.javaparser.ParserConfiguration;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
import org.opengauss.evaluate.paeser.FilesOperation;
import org.opengauss.evaluate.paeser.config.AssessmentInfoManager;
import org.opengauss.evaluate.paeser.sqlparser.SqlParseController;
import org.opengauss.evaluate.paeser.sqlparser.SqlParser;
import org.opengauss.evaluate.visitor.JavaAnnotationVisitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author biao.yang
 * @Description:
 * @date 2025/3/24 16:54
 */
public class JavaSqlParser implements SqlParser {

    private static final Logger LOGGER = LoggerFactory.getLogger(JavaSqlParser.class);

    private static final String OUTPUT_FILE = "sql_java";

    private static boolean hasInterfaceDeclaration(CompilationUnit cu) {
        return cu.getTypes().stream()
                .anyMatch(type -> type instanceof ClassOrInterfaceDeclaration && ((ClassOrInterfaceDeclaration) type).isInterface());
    }

    @Override
    public void parseSql() throws IOException {
        final String outputDir = AssessmentInfoManager.getSqlOutDir();
        String outPutfilename = outputDir + File.separator + OUTPUT_FILE;
        StringBuilder builder = new StringBuilder();
        File outPutFile = new File(outPutfilename);
        if (!FilesOperation.isCreateOutputFile(outPutFile, outputDir)) {
            LOGGER.warn("create object outputfile failed, it may already exists! outputfile: " + outPutfilename);
        }

        try(BufferedWriter bufWriter = FilesOperation.getBufferedWriter(outPutFile, false)){
            getJavaFileSql(builder);
            SqlParseController.writeSqlToFile(outPutFile.getName(), bufWriter, builder);
        }catch (IOException exp){
            LOGGER.warn("get object sql_statement occur IOException or SQLException.", exp);
            throw exp;
        }

    }



    private void getJavaFileSql(StringBuilder builder) throws IOException {
        // 配置Symbol Solver
        CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
        // 优先添加项目源码解析器
        Path startDir = Paths.get("E:\\Changhong\\晶澳\\code\\jasolar-system-monitor\\src\\main\\java");
        //Path startDir = Paths.get("E:\\Changhong\\晶澳\\code");
        combinedTypeSolver.add(new JavaParserTypeSolver(startDir.toFile()));
        // 其次解析JDK类型
        combinedTypeSolver.add(new ReflectionTypeSolver());

        // 若有外部JAR依赖
        // 添加mybatis-plus
        Path mybatisPlusJarPath = Paths.get("E:\\Repository\\com\\baomidou\\mybatis-plus-boot-starter\\3.5.5\\mybatis-plus-boot-starter-3.5.5.jar");
        combinedTypeSolver.add(new JarTypeSolver(mybatisPlusJarPath.toFile()));

        ParserConfiguration configuration = new ParserConfiguration();
        configuration.setSymbolResolver(new JavaSymbolSolver(combinedTypeSolver));
        final JavaParser javaParser = new JavaParser(configuration);

        try {
            Files.walk(startDir)
                    .filter(Files::isRegularFile)
                    .forEach(path -> {
                        if (path.toString().endsWith(".java")) {
                            try {
                                ParseResult<CompilationUnit> parseResult = javaParser.parse(path);
                                if (parseResult.isSuccessful() && parseResult.getResult().isPresent()) {
                                    CompilationUnit cu = parseResult.getResult().get();
                                    // 检查是否为interface
                                    if (hasInterfaceDeclaration(cu)) {
                                        final JavaAnnotationVisitor visitor = new JavaAnnotationVisitor();
                                        cu.accept(visitor, null);

                                        final List<String> parserSql = visitor.getParserSql();
                                        for (String dml : parserSql) {
                                            SqlParseController.appendJsonLine(builder, null, dml);
                                        }
                                    }
                                }
                            } catch (IOException e) {
                                LOGGER.error("parse exception. ", e);
                            }
                        }
                    });
        } catch (Exception e) {
            LOGGER.error("parse exception. ", e);
        }

    }


}
